<!DOCTYPE html>
<html>
  
<!-- Mirrored from www.dba.cn/book/electron/ELECTRONJiaoCheng/ELECTRONYingYongDaBao.html by HTTrack Website Copier/3.x [XR&CO'2014], Sun, 20 Mar 2022 10:24:06 GMT -->
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Electron 应用打包 - Electron中文手册</title>
    <link rel="stylesheet" type="text/css" href="../../skins/cms/css/min-easyui.css">
    <link rel="stylesheet" type="text/css" href="../../skins/cms/css/book.css">
    <script type="text/javascript" src="../../js/jquery.min.js"></script>
    <script type="text/javascript" src="../../skins/cms/js/m-easyui.js"></script>
    <script type="text/javascript" src="../../skins/cms/js/prettify.js"></script>
  </head>
  <body class="easyui-layout" style="text-align:left">
    <div region="north" border="false" class="group wrap header" style="height:66px;font-size:100%">
      <div class="header">
        <div class="navigation-toggle" data-tools="navigation-toggle" data-target="#navbar-1">
          <span>Electron中文手册</span>
        </div>
        <div id="elogo" class="navbar navbar-left">
          <ul>
            <li>
              <h1><a href="../index.html">Electron中文手册</a></h1>
            </li>
          </ul>
        </div>
      <div style="clear:both"></div>
    </div>
   </div>
    <div region="west" split="true" data-options="collapsedSize:0,hideExpandTool:true" title="文档目录" style="width:20%;min-width:300px;padding:5px;display:none;">
        
      <ul class="easyui-tree"> 
        <li iconcls="icon-base"><span>Electron 教程</span><ul><li iconcls="icon-gears"><a href="ELECTRONJiaoChengJianJie.html">Electron 教程简介</a></li><li iconcls="icon-gears"><a  href="ELECTRONKuaiSuRuMen.html">Electron 快速入门</a></li><li iconcls="icon-gears"><a  href="ELECTRONZhuoMianHuanJingJiCheng.html">Electron 桌面环境集成</a></li><li iconcls="icon-gears"><a  href="ELECTRONZaiXianLiXianShiJianTanCe.html">Electron 在线/离线事件探测</a></li><li iconcls="icon-gears"><a  href="ELECTRONJinCheng.html">Electron 进程</a></li><li iconcls="icon-gears"><a  href="ELECTRONZhiChiDeCHROMEMingLingXingKaiGuan.html">Electron 支持的 Chrome 命令行开关</a></li><li iconcls="icon-gears"><a  href="ELECTRONHuanJingBianLiang.html">Electron 环境变量</a></li><li iconcls="icon-gears"><a  href="ELECTRONZhiChiDePingTai.html">Electron 支持的平台</a></li><li iconcls="icon-gears"><a  href="ELECTRONYingYongBuShu.html">Electron 应用部署</a></li><li iconcls="icon-gears"><a  href="ELECTRONXiangMACAPPSTOREYingYongTiJiaoXiangDao.html">Electron 向Mac App Store 应用提交向导</a></li><li iconcls="icon-gears"><a  href="ELECTRONYingYongDaBao.html">Electron 应用打包</a></li><li iconcls="icon-gears"><a  href="ELECTRONShiYongYuanShengMoKuai.html">Electron 使用原生模块</a></li><li iconcls="icon-gears"><a  href="ELECTRONZhuJinChengDiaoShi.html">Electron 主进程调试</a></li><li iconcls="icon-gears"><a  href="ELECTRONShiYongSELENIUMHeWEBDRIVER.html">Electron 使用 Selenium 和 WebDriver</a></li><li iconcls="icon-gears"><a  href="ELECTRONDEVTOOLSKuoZhan.html">Electron DevTools扩展</a></li><li iconcls="icon-gears"><a  href="ELECTRONShiYongPEPPERFLASHChaJian.html">Electron 使用 Pepper Flash 插件</a></li><li iconcls="icon-gears"><a  href="ELECTRONShiYongWIDEVINECDMChaJian.html">Electron 使用 Widevine CDM 插件</a></li><li iconcls="icon-gears"><a  href="ELECTRONShuYuBiao.html">Electron 术语表</a></li><li iconcls="icon-gears"><a  href="ELECTRONLiPingRan.html">Electron 离屏渲染</a></li><li iconcls="icon-gears"><a  href="ELECTRONJiaoHuShiJieShiQiREPL.html">Electron 交互式解释器 (REPL)</a></li></ul></li><li iconcls="icon-base"><span>Electron API</span><ul><li iconcls="icon-gears"><a  href="../ELECTRONAPI/ELECTRONDOMFILEDuiXiang.html">Electron DOM File对象</a></li><li iconcls="icon-gears"><a  href="../ELECTRONAPI/ELECTRONDOMWEBVIEWBiaoQian.html">Electron DOM <webview> 标签</a></li><li iconcls="icon-gears"><a  href="../ELECTRONAPI/ELECTRONWINDOWOPENHanShu.html">Electron window.open 函数</a></li></ul></li><li iconcls="icon-base"><span>在主进程内可用的模块</span><ul><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONAPPMoKuai.html">Electron app 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONAUTOUPDATERMoKuai.html">Electron autoUpdater 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONBROWSERWINDOWMoKuai.html">Electron BrowserWindow 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONCONTENTTRACINGMoKuai.html">Electron contentTracing 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONDIALOGMoKuai.html">Electron dialog 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONGLOBAL-SHORTCUTMoKuai.html">Electron global-shortcut 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONIPCMAINMoKuai.html">Electron ipcMain 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONMENUMoKuai.html">Electron menu 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONMENUITEMMoKuai.html">Electron MenuItem 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONPOWERMONITORMoKuai.html">Electron powerMonitor 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONPOWERSAVEBLOCKERMoKuai.html">Electron powerSaveBlocker 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONPROTOCOLMoKuai.html">Electron protocol 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONSESSIONMoKuai.html">Electron session 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONWEBCONTENTSMoKuai.html">Electron webContents 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONTRAYMoKuai.html">Electron Tray 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiZhuJinChengNeiKeYongDeMoKuai/ELECTRONLOCALES.html">Electron Locales</a></li></ul></li><li iconcls="icon-base"><span>在渲染进程（网页）内可用的模块</span><ul><li iconcls="icon-gears"><a  href="../ZaiRanJinChengWangYeNeiKeYongDeMoKuai/ELECTRONDESKTOPCAPTURERMoKuai.html">Electron desktopCapturer 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiRanJinChengWangYeNeiKeYongDeMoKuai/ELECTRONIPCRENDERERMoKuai.html">Electron ipcRenderer 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiRanJinChengWangYeNeiKeYongDeMoKuai/ELECTRONREMOTEMoKuai.html">Electron remote 模块</a></li><li iconcls="icon-gears"><a  href="../ZaiRanJinChengWangYeNeiKeYongDeMoKuai/ELECTRONWEBFRAMEMoKuai.html">Electron webFrame 模块</a></li></ul></li><li iconcls="icon-base"><span>两种进程都可用的模块</span><ul><li iconcls="icon-gears"><a  href="../LiangZhongJinChengDuKeYongDeMoKuai/ELECTRONCLIPBOARDMoKuai.html">Electron clipboard 模块</a></li><li iconcls="icon-gears"><a  href="../LiangZhongJinChengDuKeYongDeMoKuai/ELECTRONCRASHREPORTERMoKuai.html">Electron crashReporter 模块</a></li><li iconcls="icon-gears"><a  href="../LiangZhongJinChengDuKeYongDeMoKuai/ELECTRONNATIVEIMAGEMoKuai.html">Electron nativeImage 模块</a></li><li iconcls="icon-gears"><a  href="../LiangZhongJinChengDuKeYongDeMoKuai/ELECTRONSCREENMoKuai.html">Electron screen 模块</a></li><li iconcls="icon-gears"><a  href="../LiangZhongJinChengDuKeYongDeMoKuai/ELECTRONSHELLMoKuai.html">Electron shell 模块</a></li></ul></li><li iconcls="icon-base"><span>Electron 开发</span><ul><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONBianMaGuiFan.html">Electron 编码规范</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONYuanMaMuLuJieGou.html">Electron 源码目录结构</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONHeNWJSYuanMingNODE-WEBKITZaiJiShuShangDeChaYi.html">Electron 和 NW.js (原名 node-webkit) 在技术上的差异</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONGouJianXiTongGaiLan.html">Electron 构建系统概览</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONGouJianBuZhouOSX.html">Electron 构建步骤 (OS X)</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONGouJianBuZhouWINDOWS.html">Electron 构建步骤 (Windows)</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONGouJianBuZhouLINUX.html">Electron 构建步骤 (Linux)</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONZaiDiaoShiZhongShiYongSYMBOLSERVER.html">Electron 在调试中使用 Symbol Server</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONChangJianWenTi.html">Electron 常见问题</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONBanBenGuanLi.html">Electron 版本管理</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONWINDOWTiJiaoZhiNan.html">electron window 提交指南</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ZiDongHuaChiXuJiChengXiTongCICeShi.html">自动化持续集成系统（CI）测试</a></li><li iconcls="icon-gears"><a  href="../ELECTRONKaiFa/ELECTRONWenDangFengGeZhiNan.html">Electron 文档风格指南</a></li></ul></li>
      </ul>
    
    </div>
    <div region="center">
      <div id="tt" class="easyui-tabs" fit="true" border="false" plain="true">
        <div title="Electron 应用打包 - Electron中文手册">  
            <div class="book-content">
              
      <div style="padding:8px;"> &gt; <a href="../index.html">Electron中文手册</a> &gt; Electron 应用打包</div>
      <div class="content"><p class="comments-section">为舒缓 Windows 下路径名过长的问题issues，也略对 <code>require</code> 加速以及简单隐匿你的源代码，你可以通过极小的源代码改动将你的应用打包成 asar。</p>
<h2 id="生成-asar-包">生成 <code>asar</code> 包</h2>
<p class="comments-section">asar 是一种将多个文件合并成一个文件的类 tar 风格的归档格式。Electron 可以无需解压，即从其中读取任意文件内容。</p>
<p class="comments-section">参照如下步骤将你的应用打包成 <code>asar</code>：</p>
<h3 id="1-安装-asar">1. 安装 asar</h3>
<pre><code class="lang-bash">$ npm install -g asar
</code></pre>
<h3 id="2-用-asar-pack-打包">2. 用 <code>asar pack</code> 打包</h3>
<pre><code class="lang-bash">$ asar pack your-app app.asar
</code></pre>
<h2 id="使用-asar-包">使用 <code>asar</code> 包</h2>
<p class="comments-section">在 Electron 中有两类 APIs：Node.js 提供的 Node API 和 Chr<a href="../../omi/index.html">omi</a>um 提供的 Web API。这两种 API 都支持从 <code>asar</code> 包中读取文件。</p>
<h3 id="node-api">Node API</h3>
<p class="comments-section">由于 Electron 中打了特别补丁， Node API 中如 <code>fs.readFile</code> 或者 <code>require</code> 之类的方法可以将 <code>asar</code> 视之为虚拟文件夹，读取 <code>asar</code> 里面的文件就和从真实的文件系统中读取一样。</p>
<p class="comments-section">例如，假设我们在 <code>/path/to</code> 文件夹下有个 <code>example.asar</code> 包：</p>
<pre><code class="lang-bash">$ asar list /path/to/example.asar
/app.js
/file.txt
/dir/module.js
/static/index.<a href="../../html/index.html">HTML</a>
/static/main.css
/static/jquery.min.js
</code></pre>
<p class="comments-section">从 <code>asar</code> 包读取一个文件：</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
fs.readFileSync(<span class="hljs-string">'/path/to/example.asar/file.txt'</span>);
</code></pre>
<p class="comments-section">列出 <code>asar</code> 包中根目录下的所有文件：</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
fs.readdirsync(<span class="hljs-string">'/path/to/example.asar'</span>);
</code></pre>
<p class="comments-section">使用 <code>asar</code> 包中的一个模块：</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">require</span>(<span class="hljs-string">'/path/to/example.asar/dir/module.js'</span>);
</code></pre>
<p class="comments-section">你也可以使用 <code>BrowserWindow</code> 来显示一个 <code>asar</code> 包里的 web 页面：</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> BrowserWindow = <span class="hljs-built_in">require</span>(<span class="hljs-string">'electron'</span>).BrowserWindow;
<span class="hljs-keyword">var</span> win = <span class="hljs-keyword">new</span> BrowserWindow({width: <span class="hljs-number">800</span>, height: <span class="hljs-number">600</span>});
win.loadURL(<span class="hljs-string">'file:///path/to/example.asar/static/index.html'</span>);
</code></pre>
<h3 id="web-api">Web API</h3>
<p class="comments-section">在 Web 页面里，用 <code>file:</code> 协议可以获取 <code>asar</code> 包中文件。和 Node API 一样，视 <code>asar</code> 包如虚拟文件夹。</p>
<p class="comments-section">例如，用 <code>$.get</code> 获取文件:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-title">script</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">var</span> $ = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./jquery.min.js'</span>);
$.get(<span class="hljs-string">'file:///path/to/example.asar/file.txt'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>) </span>{
  <span class="hljs-built_in">console</span>.log(data);
});
</span><span class="hljs-tag">&lt;/<span class="hljs-title">script</span>&gt;</span>
</code></pre>
<h3 id="像文件那样处理-asar-包">像“文件”那样处理 <code>asar</code> 包</h3>
<p class="comments-section">有些场景，如：核查 <code>asar</code> 包的校验和，我们需要像读取“文件”那样读取 <code>asar</code> 包的内容(而不是当成虚拟文件夹)。你可以使用内置的 <code>original-fs</code> （提供和 <code>fs</code> 一样的 API）模块来读取 <code>asar</code> 包的真实信息。</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> originalFs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'original-fs'</span>);
originalFs.readFileSync(<span class="hljs-string">'/path/to/example.asar'</span>);
</code></pre>
<h2 id="node-api-缺陷">Node API 缺陷</h2>
<p class="comments-section">尽管我们已经尽了最大努力使得 <code>asar</code> 包在 Node API 下的应用尽可能的趋向于真实的目录结构，但仍有一些底层 Node API 我们无法保证其正常工作。</p>
<h3 id="asar-包是只读的">
<code>asar</code> 包是只读的</h3>
<p class="comments-section"><code>asar</code> 包中的内容不可更改，所以 Node APIs 里那些可以用来修改文件的方法在对待 <code>asar</code> 包时都无法正常工作。</p>
<h3 id="working-directory-在-asar-包中无效">Working Directory 在 <code>asar</code> 包中无效</h3>
<p class="comments-section">尽管 <code>asar</code> 包是虚拟文件夹，但其实并没有真实的目录架构对应在文件系统里，所以你不可能将 working Directory 设置成 <code>asar</code> 包里的一个文件夹。将 <code>asar</code> 中的文件夹以 <code>cwd</code> 形式作为参数传入一些 API 中也会报错。</p>
<h3 id="api-中的额外开箱">API 中的额外“开箱”</h3>
<p class="comments-section">大部分 <code>fs</code> API 可以无需解压即从 <code>asar</code> 包中读取文件或者文件的信息，但是在处理一些依赖真实文件路径的底层系统方法时，Electron 会将所需文件解压到临时目录下，然后将临时目录下的真实文件路径传给底层系统方法使其正常工作。 对于这类API，耗费会略多一些。</p>
<p class="comments-section">以下是一些需要额外解压的 API：</p>
<ul>
<li><code>child_process.execFile</code></li>
<li><code>child_process.execFileSync</code></li>
<li><code>fs.open</code></li>
<li><code>fs.openSync</code></li>
<li>
<code>process.dlopen</code> - <code>require</code>native模块时用到</li>
</ul>
<h3 id="fsstat-获取的-stat-信息不可靠">
<code>fs.stat</code> 获取的 stat 信息不可靠</h3>
<p class="comments-section">对 <code>asar</code> 包中的文件取 <code>fs.stat</code>，返回的 <code>Stats</code> 对象不是精确值，因为这些文件不是真实存在于文件系统里。所以除了文件大小和文件类型以外，你不应该依赖 <code>Stats</code> 对象的值。</p>
<h3 id="执行-asar-包中的程序">执行 <code>asar</code> 包中的程序</h3>
<p class="comments-section">Node 中有一些可以执行程序的 API，如 <code>child_process.exec</code>，<code>child_process.spawn</code> 和 <code>child_process.execFile</code> 等，但只有 <code>execFile</code> 可以执行 <code>asar</code> 包中的程序。</p>
<p class="comments-section">因为 <code>exec</code> 和 <code>spawn</code> 允许 <code>command</code> 替代 <code>file</code> 作为输入，而 <code>command</code> 是需要在 <a href="../../shell/index.html">shell</a> 下执行的，目前没有可靠的方法来判断 <code>command</code> 中是否在操作一个 <code>asar</code> 包中的文件，而且即便可以判断，我们依旧无法保证可以在无任何副作用的情况下替换 <code>command</code> 中的文件路径。</p>
<h2 id="打包时排除文件">打包时排除文件</h2>
<p class="comments-section">如上所述，一些 Node API 会在调用时将文件解压到文件系统中，除了效率问题外，也有可能引起杀毒软件的注意！</p>
<p class="comments-section">为解决这个问题，你可以在生成 <code>asar</code> 包时使用 <code>--unpack</code> 选项来排除一些文件，使其不打包到 <code>asar</code> 包中，下面是如何排除一些用作共享用途的 native 模块的方法：</p>
<pre><code class="lang-bash">$ asar pack app app.asar --unpack *.node
</code></pre>经过上述命令后，除了生成的 <code>app.asar</code> 包以外，还有一个包含了排除文件的 <code>app.asar.unpacked</code> 文件夹，你需要将这个文件夹一起拷贝，提供给用户。</div>
      <div class="prev-next" style="padding:8px;">上一篇：<a class="prev" href="ELECTRONXiangMACAPPSTOREYingYongTiJiaoXiangDao.html">Electron 向Mac App Store 应用提交向导</a><br>下一篇：<a class="prev" href="ELECTRONShiYongYuanShengMoKuai.html">Electron 使用原生模块</a><br></div>
    
            </div>
        </div> 
      </div>
    </div>
  </body>

<!-- Mirrored from www.dba.cn/book/electron/ELECTRONJiaoCheng/ELECTRONYingYongDaBao.html by HTTrack Website Copier/3.x [XR&CO'2014], Sun, 20 Mar 2022 10:24:06 GMT -->
</html>